package com.ufo.utils.beanutils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.converters.AbstractArrayConverter;
import org.apache.log4j.Logger;

public class ObjectUtil {
	public static final Logger log = Logger.getLogger(ObjectUtil.class);
	public static final String SETTER_PREFIX = "set";

	static {
		BeanUtilsBean util = BeanUtilsBean.getInstance();
		util.getConvertUtils().register(new IntegerArrayConverter(), int[].class);
	}

	public static void main(String[] args) {
		String name = getSimpleName(ObjectUtil.class);
		System.out.println(name);
	}

	public static Object copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
		BeanUtils.copyProperties(dest, orig);
		return dest;
	}

	public static void copyByFields(Object dest, Object orig, boolean excludeNull) {
		Field[] fields = orig.getClass().getDeclaredFields();
		for (int i = 0; i < fields.length; i++)
			try {
				fields[i].setAccessible(true);
				if (Modifier.isFinal(fields[i].getModifiers())) {
					continue;
				}
				Object value = fields[i].get(orig);
				if (excludeNull) {
					if (value != null)
						fields[i].set(dest, value);
				} else
					fields[i].set(dest, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
	}

	public static Collection getClassAllFields(Class clazz) {
		Collection rtn = new ArrayList();
		Class current = clazz;

		while (current != null) {
			Field[] fields = current.getDeclaredFields();
			rtn.addAll((Collection) Arrays.asList(fields));

			current = current.getSuperclass();
		}

		return rtn;
	}

	public static void setProperty(Object bean, String name, Object value) {
		setProperty(bean, name, value, true);
	}

	public static void setProperty(Object bean, String name, Object value, boolean caseSensitive) {
		if (value == null) {
			return;
		}
		Method[] methods = bean.getClass().getMethods();// methods是传进来的bean的所有方法
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			StringBuffer methodName = new StringBuffer(name);
			methodName.setCharAt(0, Character.toUpperCase(methodName.charAt(0)));
			methodName.insert(0, "set");// 给传进来的name加一个set(这个name就是数据库表对应的列名colName)

			if (caseSensitive) {
				if (method.getName().equals(methodName.toString())) {
					invokeMethod(bean, method, new Object[] { value });
				}
			} else if (method.getName().equalsIgnoreCase(methodName.toString()))
				invokeMethod(bean, method, new Object[] { value });
		}
	}

	public static Collection getWriteMethods(Object bean) {
		Collection rtn = new ArrayList();

		Method[] methods = bean.getClass().getMethods();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i].getName().startsWith("set")) {
				rtn.add(methods[i]);
			}
		}
		return rtn;
	}

	public static void invokeMethod(Object bean, Method method, Object[] values) {
		try {
			boolean allowInvoke = true;

			Class[] paramClazzs = method.getParameterTypes();

			if (paramClazzs.length != values.length)
				allowInvoke = false;
			else {
				for (int i = 0; i < paramClazzs.length; i++) {
					if ((!paramClazzs[i].isAssignableFrom(values[i].getClass())) && (!paramClazzs[i].isPrimitive())) {
						allowInvoke = false;
						break;
					}
				}
			}

			if (allowInvoke)
				method.invoke(bean, values);
		} catch (IllegalArgumentException e) {
			log.debug(method.getName() + " error: " + e.getMessage());
		} catch (IllegalAccessException e) {
			log.debug(method.getName() + " error: " + e.getMessage());
		} catch (InvocationTargetException e) {
			log.debug(method.getName() + " error: " + e.getMessage());
		}
	}

	/**
	 * 克隆对象
	 * 
	 * @param origObj
	 *            被克隆的对象
	 * @return
	 */
	public static Object clone(Object origObj) {
		try {
			ByteArrayOutputStream bout = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bout);
			out.writeObject(origObj);// 写入ByteArrayOutputStream内存缓冲区
			out.close();

			ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
			ObjectInputStream in = new ObjectInputStream(bin);
			Object newObj = in.readObject();// 再把内存缓冲区的对象读出来
			in.close();

			return newObj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String getSimpleName(Class clazz) {
		String fullName = clazz.getName();
		String simpleName = fullName.substring(fullName.lastIndexOf(".") + 1, fullName.length());
		return simpleName;
	}

	public static class IntegerArrayConverter extends AbstractArrayConverter {
		int[] model = new int[0];
		Object[] objects = new Object[0];

		public Object convert(Class type, Object value) {
			if (value == null) {
				if (this.useDefault) {
					return this.defaultValue;
				}
				throw new ConversionException("No value specified");
			}

			if (this.model.getClass() == value.getClass()) {
				return value;
			}

			if (strings.getClass() == value.getClass()) {
				try {
					String[] values = (String[]) value;
					int[] results = new int[values.length];
					for (int i = 0; i < values.length; i++) {
						results[i] = Integer.parseInt(values[i]);
					}
					return results;
				} catch (Exception e) {
					if (this.useDefault) {
						return this.defaultValue;
					}
					throw new ConversionException(value.toString(), e);
				}

			}

			if (this.objects.getClass() == value.getClass()) {
				try {
					Object[] values = (Object[]) value;
					int[] results = new int[values.length];

					for (int i = 0; i < values.length; i++) {
						if (values[i].getClass() == Integer.class)
							results[i] = ((Integer) values[i]).intValue();
						else if (values[i].getClass() == String.class) {
							results[i] = Integer.parseInt((String) values[i]);
						}
					}

					return results;
				} catch (Exception e) {
					if (this.useDefault) {
						return this.defaultValue;
					}
					throw new ConversionException(value.toString(), e);
				}

			}

			try {
				List list = parseElements(value.toString());
				int[] results = new int[list.size()];
				for (int i = 0; i < results.length; i++) {
					results[i] = Integer.parseInt((String) list.get(i));
				}
				return results;
			} catch (Exception e) {
				if (this.useDefault)
					return this.defaultValue;
				else
					throw new ConversionException(value.toString(), e);
			}

		}
	}
}